import BaseController from './BaseController.js';
import db from '../models/index.js';
import { StatusCodes } from 'http-status-codes';
import { Op } from 'sequelize';
import { AppError } from '../middlewares/error.js';

const { Enrollment, Course, User } = db;

class EnrollmentController extends BaseController {
  constructor() {
    super();
  }

  /**
   * 学生选课
   */
  async enrollCourse(req, res, next) {
    try {
      const { courseId } = req.params;
      const studentId = req.user.id;

      // 1) 检查用户角色
      if (req.user.role !== User.ROLES.STUDENT) {
        return next(
          new AppError('只有学生可以选课', StatusCodes.FORBIDDEN)
        );
      }

      // 2) 检查课程是否存在
      const course = await Course.findByPk(courseId);
      if (!course) {
        return next(
          new AppError('未找到该课程', StatusCodes.NOT_FOUND)
        );
      }

      // 3) 检查课程状态
      if (course.status !== 'published') {
        return next(
          new AppError('该课程未开放选课', StatusCodes.BAD_REQUEST)
        );
      }

      // 4) 检查课程是否已满
      if (course.isFull()) {
        return next(
          new AppError('该课程已满，无法选课', StatusCodes.BAD_REQUEST)
        );
      }

      // 5) 检查是否已选该课程
      const existingEnrollment = await Enrollment.findOne({
        where: {
          studentId,
          courseId,
          status: Enrollment.STATUS.SELECTED
        }
      });

      if (existingEnrollment) {
        return next(
          new AppError('您已经选择了该课程', StatusCodes.BAD_REQUEST)
        );
      }

      // 6) 检查是否有未完成的相同课程
      const existingCourseEnrollment = await Enrollment.findOne({
        where: {
          studentId,
          courseId,
          status: {
            [Enrollment.Sequelize.Op.in]: [
              Enrollment.STATUS.SELECTED,
              Enrollment.STATUS.COMPLETED
            ]
          }
        }
      });

      if (existingCourseEnrollment) {
        return next(
          new AppError('您已经选择或完成了该课程', StatusCodes.BAD_REQUEST)
        );
      }

      // 7) 创建选课记录
      const enrollment = await Enrollment.create({
        studentId,
        courseId,
        status: Enrollment.STATUS.SELECTED
      });

      // 8) 更新课程当前选课人数
      await course.increment('currentEnrollment');

      this.success(res, enrollment, '选课成功', StatusCodes.CREATED);
    } catch (error) {
      this.error(res, '选课失败', StatusCodes.INTERNAL_SERVER_ERROR, error);
    }
  }

  /**
   * 学生退课
   */
  async dropCourse(req, res, next) {
    try {
      const { courseId } = req.params;
      const studentId = req.user.id;

      // 1) 检查用户角色
      if (req.user.role !== User.ROLES.STUDENT) {
        return next(
          new AppError('只有学生可以退课', StatusCodes.FORBIDDEN)
        );
      }

      // 2) 查找选课记录
      const enrollment = await Enrollment.findOne({
        where: {
          studentId,
          courseId,
          status: Enrollment.STATUS.SELECTED
        },
        include: [
          {
            model: Course,
            as: 'course',
            attributes: ['id', 'name', 'teacherId', 'currentEnrollment']
          }
        ]
      });

      if (!enrollment) {
        return next(
          new AppError('未找到您的选课记录或课程已结束', StatusCodes.NOT_FOUND)
        );
      }

      // 3) 检查是否允许退课（例如：课程是否已开始）
      // 这里可以添加更多业务规则

      // 4) 更新选课状态为已退选
      await enrollment.update({
        status: Enrollment.STATUS.DROPPED,
        droppedAt: new Date()
      });

      // 5) 更新课程当前选课人数
      if (enrollment.course && enrollment.course.currentEnrollment > 0) {
        await enrollment.course.decrement('currentEnrollment');
      }

      this.success(res, null, '退课成功');
    } catch (error) {
      this.error(res, '退课失败', StatusCodes.INTERNAL_SERVER_ERROR, error);
    }
  }

  /**
   * 获取我的选课列表（学生）
   */
  async getMyEnrollments(req, res, next) {
    try {
      // 1) 检查用户角色
      if (req.user.role !== User.ROLES.STUDENT) {
        return next(
          new AppError('只有学生可以查看选课记录', StatusCodes.FORBIDDEN)
        );
      }

      const { 
        page = 1, 
        limit = 10, 
        status,
        sortBy = 'enrolledAt',
        sortOrder = 'DESC'
      } = req.query;

      const where = { studentId: req.user.id };
      if (status) where.status = status;

      // 排序
      const order = [];
      if (sortBy) {
        order.push([sortBy, sortOrder || 'DESC']);
      }

      // 查询选课记录及关联的课程信息
      const result = await Enrollment.findAndCountAll({
        where,
        include: [
          {
            model: Course,
            as: 'course',
            include: [
              {
                model: User,
                as: 'teacher',
                attributes: ['id', 'name', 'email']
              }
            ]
          }
        ],
        order,
        offset: (page - 1) * limit,
        limit: parseInt(limit, 10),
        distinct: true
      });

      this.success(res, {
        total: result.count,
        page: parseInt(page, 10),
        limit: parseInt(limit, 10),
        data: result.rows,
      }, '获取成功');
    } catch (error) {
      this.error(res, '获取选课记录失败', StatusCodes.INTERNAL_SERVER_ERROR, error);
    }
  }

  /**
   * 获取课程的学生列表（教师）
   */
  async getCourseEnrollments(req, res, next) {
    try {
      const { courseId } = req.params;

      // 1) 检查课程是否存在
      const course = await Course.findByPk(courseId);
      if (!course) {
        return next(
          new AppError('未找到该课程', StatusCodes.NOT_FOUND)
        );
      }

      // 2) 检查权限：课程创建者或管理员
      if (course.teacherId !== req.user.id && req.user.role !== User.ROLES.ADMIN) {
        return next(
          new AppError('您没有权限查看该课程的学生列表', StatusCodes.FORBIDDEN)
        );
      }

      const { 
        page = 1, 
        limit = 10, 
        status,
        sortBy = 'enrolledAt',
        sortOrder = 'DESC'
      } = req.query;

      const where = { courseId };
      if (status) where.status = status;

      // 排序
      const order = [];
      if (sortBy) {
        order.push([sortBy, sortOrder || 'DESC']);
      }

      // 查询选课记录及关联的学生信息
      const result = await Enrollment.findAndCountAll({
        where,
        include: [
          {
            model: User,
            as: 'student',
            attributes: ['id', 'name', 'email', 'phone']
          }
        ],
        order,
        offset: (page - 1) * limit,
        limit: parseInt(limit, 10),
        distinct: true
      });

      this.success(res, {
        total: result.count,
        page: parseInt(page, 10),
        limit: parseInt(limit, 10),
        data: result.rows,
      }, '获取成功');
    } catch (error) {
      this.error(res, '获取学生列表失败', StatusCodes.INTERNAL_SERVER_ERROR, error);
    }
  }

  /**
   * 给学生评分（教师）
   */
  async gradeStudent(req, res, next) {
    try {
      const { enrollmentId } = req.params;
      const { score, feedback } = req.body;

      // 1) 检查评分是否有效
      if (score === undefined || score === null) {
        return next(
          new AppError('请提供成绩', StatusCodes.BAD_REQUEST)
        );
      }

      if (score < 0 || score > 100) {
        return next(
          new AppError('成绩必须在0-100之间', StatusCodes.BAD_REQUEST)
        );
      }

      // 2) 查找选课记录
      const enrollment = await Enrollment.findByPk(enrollmentId, {
        include: [
          {
            model: Course,
            as: 'course',
            attributes: ['id', 'teacherId']
          }
        ]
      });

      if (!enrollment) {
        return next(
          new AppError('未找到选课记录', StatusCodes.NOT_FOUND)
        );
      }

      // 3) 检查权限：课程创建者或管理员
      if (enrollment.course.teacherId !== req.user.id && req.user.role !== User.ROLES.ADMIN) {
        return next(
          new AppError('您没有权限给该学生评分', StatusCodes.FORBIDDEN)
        );
      }

      // 4) 更新成绩和反馈
      const updatedEnrollment = await enrollment.update({
        score,
        feedback,
        status: score >= 60 ? Enrollment.STATUS.COMPLETED : Enrollment.STATUS.FAILED
      });

      this.success(res, updatedEnrollment, '评分成功');
    } catch (error) {
      this.error(res, '评分失败', StatusCodes.INTERNAL_SERVER_ERROR, error);
    }
  }

  /**
   * 获取我的成绩单（学生）
   */
  async getMyTranscript(req, res, next) {
    try {
      // 1) 检查用户角色
      if (req.user.role !== User.ROLES.STUDENT) {
        return next(
          new AppError('只有学生可以查看成绩单', StatusCodes.FORBIDDEN)
        );
      }

      // 2) 查询已完成的课程
      const completedCourses = await Enrollment.findAll({
        where: {
          studentId: req.user.id,
          status: {
            [Enrollment.Sequelize.Op.in]: [
              Enrollment.STATUS.COMPLETED,
              Enrollment.STATUS.FAILED
            ]
          }
        },
        include: [
          {
            model: Course,
            as: 'course',
            attributes: ['id', 'name', 'credit']
          }
        ],
        order: [['updatedAt', 'DESC']]
      });

      // 3) 计算总学分和GPA
      let totalCredits = 0;
      let totalGradePoints = 0;

      const transcript = completedCourses.map(enrollment => {
        const course = enrollment.course;
        const credit = parseFloat(course.credit) || 0;
        const gradePoint = this.calculateGradePoint(enrollment.score);
        const gradePoints = credit * gradePoint;

        totalCredits += credit;
        totalGradePoints += gradePoints;

        return {
          courseId: course.id,
          courseName: course.name,
          credit: course.credit,
          score: enrollment.score,
          status: enrollment.status,
          grade: this.calculateGrade(enrollment.score),
          gradePoint,
          gradePoints,
          feedback: enrollment.feedback,
          completedAt: enrollment.updatedAt
        };
      });

      const gpa = totalCredits > 0 ? (totalGradePoints / totalCredits).toFixed(2) : 0;

      this.success(res, {
        studentId: req.user.id,
        studentName: req.user.name,
        totalCredits,
        gpa: parseFloat(gpa),
        courses: transcript,
        completedCourses: transcript.length
      }, '获取成绩单成功');
    } catch (error) {
      this.error(res, '获取成绩单失败', StatusCodes.INTERNAL_SERVER_ERROR, error);
    }
  }

  /**
   * 计算成绩等级
   */
  calculateGrade(score) {
    if (score >= 90) return 'A';
    if (score >= 80) return 'B';
    if (score >= 70) return 'C';
    if (score >= 60) return 'D';
    return 'F';
  }

  /**
   * 计算绩点
   */
  calculateGradePoint(score) {
    if (score >= 90) return 4.0;
    if (score >= 85) return 3.7;
    if (score >= 82) return 3.3;
    if (score >= 78) return 3.0;
    if (score >= 75) return 2.7;
    if (score >= 72) return 2.3;
    if (score >= 68) return 2.0;
    if (score >= 64) return 1.5;
    if (score >= 60) return 1.0;
    return 0.0;
  }
}

export default new EnrollmentController();
